Flutter PlatformViewLayer

PlatformViewLayer 是 Flutter Layer 的一种,用于 Hybrid composition 模式下的 UI 展示。

该类在 Flutter 中有两套实现:


Dart 实现

RenderObject 的 Layer 要通过 SceneBuilder 添加到 Scene 上,对应实现:

@override
void addToScene(ui.SceneBuilder builder) {
  builder.addPlatformView(
    viewId,
    offset: rect.topLeft,
    width: rect.width,
    height: rect.height,
  );
}

Flutter SceneBuilder 是从 Flutter Engine C++ 侧映射到 Dart 的类,这个调用将会调用 Flutter SceneBuilder 内的 C++ 方法。

而在 SceneBuilder 的 C++ 方法中,会创建一个 C++ 的 PlatformViewLayer 类,添加到 C++ 层的 LayerTree 中。这个 C++ 层的 LayerTree,将会传给 GPU 线程进行光栅化。


C++ 实现

类声明如下,通过对比可以清晰看出,类属性与 Dart 侧一致。核心在与 Preroll 和 paint 两个方法:

class PlatformViewLayer : public Layer {
 public:
  PlatformViewLayer(const SkPoint& offset, const SkSize& size, int64_t view_id);

  void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
  void Paint(PaintContext& context) const override;

 private:
  SkPoint offset_;
  SkSize size_;
  int64_t view_id_;

  FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewLayer);
};

Preroll

代码实现如下:

void PlatformViewLayer::Preroll(PrerollContext* context,
                                const SkMatrix& matrix) {
  // 设置了平台视图的绘制边界
  set_paint_boundsMakeXYWH(offset_.x(), offset_.y(), size_.width(,
                                    size_.height()));

  if (context->view_embedder == nullptr) {
    FML_LOG(ERROR) << "Trying to embed a platform view but the PrerollContext "
                      "does not support embedding";
    return;
  }
  // 表示这个上下文包含一个平台视图。
  context->has_platform_view = true;
  // 表示这个层的子树包含一个平台视图。
  set_subtree_has_platform_view(true);
  std::unique_ptr<EmbeddedViewParams> params =
      std::make_unique<EmbeddedViewParams>(matrix, size_,
                                           context->mutators_stack);
  context->view_embedder->PrerollCompositeEmbeddedView(view_id_,
                                                       std::move(params));
}

其中,在 Android 下,PrerollCompositeEmbeddedView 将调用 AndroidExternalViewEmbedder 的 PrerollCompositeEmbeddedView 方法,在该方法内,实现了在 C++ 底层,对 PlatformView 的在真正渲染前的底层准备工作。

Paint

Paint 是 Hybrid composition 模式下,Flutter 侧 PlatformViewLayer 最底层的绘制方法。从 SkCanvas 中取出 AndroidExternalViewEmbedder 执行 CompositeEmbeddedView。

void PlatformViewLayer::Paint(PaintContext& context) const {
  if (context.view_embedder == nullptr) {
    FML_LOG(ERROR) << "Trying to embed a platform view but the PaintContext "
                      "does not support embedding";
    return;
  }
  SkCanvas* canvas = context.view_embedder->CompositeEmbeddedView(view_id_);
  context.leaf_nodes_canvas = canvas;
}

在 AndroidExternalViewEmbedder 的 CompositeEmbeddedView 方法中,

// |ExternalViewEmbedder|
SkCanvas* AndroidExternalViewEmbedder::CompositeEmbeddedView(int view_id) {
  if (picture_recorders_.count(view_id) == 1) {
    return picture_recorders_.at(view_id)->getRecordingCanvas();
  }
  return nullptr;
}

网络资源


本文作者:Maeiee

本文链接:Flutter PlatformViewLayer

版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!


喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!